		TITLE	FIXUPP - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	GROUPS
		INCLUDE	FIXTEMPS
		INCLUDE	CDDATA

		.DATA

		EXTERNDEF	NEW_FIXUPP:BYTE,TEMP_DATA_RECORD:BYTE,CLASS_TYPE:BYTE,LDATA_TYPE:BYTE,FARCALL_FIXUPP:BYTE
		EXTERNDEF	REFERENCE_FLAGS:BYTE

		EXTERNDEF	GRP_COUNT:DWORD,EXTERNAL_COUNT:DWORD,END_OF_RECORD:DWORD,LDATA_LENGTH:DWORD,NUMBLKS:DWORD
		EXTERNDEF	BUFFER_OFFSET:DWORD,EXTDEF_DELTA:DWORD,DEFAULT_SIZE:DWORD,LDATA_SEGMOD_GINDEX:DWORD
		EXTERNDEF	CURNMOD_GINDEX:DWORD,LATEST_PENT_GINDEX:DWORD,MODEND_OWNER_GINDEX:DWORD,GRP_LIST:DWORD
		EXTERNDEF	LAST_DATA_PTR:DWORD,LDATA_LOC:DWORD,PREV_DATA_PTR:DWORD,LAST_FARCALL:DWORD,FIRST_FARCALL:DWORD
		EXTERNDEF	MODEND_ADDRESS:DWORD,LOC_11_FIX:DWORD

		EXTERNDEF	GROUP_LARRAY:LARRAY_STRUCT,SEGMOD_LARRAY:LARRAY_STRUCT,SYMBOL_LARRAY:LARRAY_STRUCT
		EXTERNDEF	SYMBOL_GARRAY:STD_PTR_S,SEGMOD_GARRAY:STD_PTR_S,SEGMENT_GARRAY:STD_PTR_S,GROUP_GARRAY:STD_PTR_S

		EXTERNDEF	PRE_THREADS:THREAD_STUFF_STRUCT


		.CODE	PASS1_TEXT

		EXTERNDEF	FIXUPP_ALLOC:PROC,LDATA_ALLOC:PROC,LEDATA_CONT:PROC,INSTALL_PENT:PROC,FIXUPP_ERROR:PROC
		EXTERNDEF	OBJ_PHASE:PROC,FARCALL_ALLOC:PROC,ERR_ABORT:PROC,RETURN_LOWEST_SECTION:PROC,INSTALL_PUBALLOC:PROC
		EXTERNDEF	INSTALL_LIBALLOC:PROC,INSTALL_SOFT_REF:PROC,INSTALL_SOFT_PENT:PROC

		EXTERNDEF	FIXUPP_OFFSET_ERR:ABS,UNREC_FIXUPP_ERR:ABS,BAD_THREAD_ERR:ABS,BAD_LOC_ERR:ABS,LIDATA_ERR:ABS
		EXTERNDEF	UNRECOGNIZED_FIXUPP_FRAME_ERR:ABS


struct FIX_VARS
{
    SEGMOD_STRUCT FIX_SEGMOD_STUFF_BP;
    void* FIX_FARCALL_PTR_BP;	// FIXUPP
    void* FIX_NEW_PTR_BP;	// FIXUPP
    void* FIX_OFFSET_BP;	// FIXUPP
    void* FIX_LDATA_PTR_BP;	// FIXUPP - PHYSICAL ADDRESS
    void* FIX_LDATA_BLK_BP;
    THREAD_STUFF_STRUCT FIX_FRAME_STUFF_BP;
    THREAD_STUFF_STRUCT FIX_TARGET_STUFF_BP;
    int FIX_LOC_BP;			// FIXUPP - NEXT NEED ODD BYTE
    int FIX_TOFFSET_BP;			// FIXUPP
    int FIX_LDATA_GROUP_GINDEX_BP;	// FIXUPP
    int FIX_LDATA_SEGMENT_GINDEX_BP;	// FIXUPP
    int FIXUPP_COUNT_BP;
    int FIX_END_OF_RECORD_BP;

    ubyte FIX_NSYM_TYPE_BP;
    ubyte FIX_SIZE_BP;			// FIXUPP&MODEND
    ubyte FIX_SKIP_PENTS_BP;
    ubyte FIX_COMDAT_PENTS_BP;

    int FIX_OS2_FLAGS_BP;
    int FIX_ESP_SAVE_BP;
}

FIX	MACRO	X

X	EQU	([EBP - SIZE FIX_VARS].(X&_BP))

	ENDM

FIX	FIX_SEGMOD_STUFF
FIX	FIX_FARCALL_PTR
FIX	FIX_NEW_PTR
FIX	FIX_OFFSET
FIX	FIX_LDATA_PTR
FIX	FIX_LDATA_BLK
FIX	FIX_FRAME_STUFF
FIX	FIX_TARGET_STUFF
FIX	FIX_LOC
FIX	FIX_SIZE
FIX	FIX_TOFFSET
FIX	FIX_LDATA_GROUP_GINDEX
FIX	FIX_LDATA_SEGMENT_GINDEX
FIX	FIXUPP_COUNT
FIX	FIX_END_OF_RECORD
FIX	FIX_NSYM_TYPE
FIX	FIX_OS2_FLAGS
FIX	FIX_SKIP_PENTS
FIX	FIX_COMDAT_PENTS
FIX	FIX_ESP_SAVE


		ASSUME	EBP:PTR FIX_VARS

SCAN_FOR_THREADS()
{
	// skipping, so ok except that we must look for any thread
	// types so that threads are maintained...

	EBX = END_OF_RECORD;
	EDX = 2;
	EDI = &NEW_FIXUPP;
	AL = EBP.FIX_SIZE;
	AL &= MASK BIT_32;
	if (AL)
		EDX *= 2;
	LDI_LOOP();
}

LDI_LOOP()
{
	if (EBX BE ESI)
		goto DONE;

	AL = [ESI];
	++ESI;

	if (AL & 80H)
	// THREAD, JUMP
		JZ	HELP

	// skip this entry


	AL = [ESI+1];
	ESI += 2;

	CL = AL;
	if (AL & 0C0H)

	CH = [ESI];
		JNZ	NO_FRAME_INDEX

	AL &= 30H;
	++ESI;

	if (AL == 30H)
		goto FORCE_2;

	CH &= 80H;
		JZ	NO_FRAME_INDEX
FORCE_2:
	++ESI;

NO_FRAME_INDEX	LABEL	PROC

	if (CL & 8)
		JNZ	NO_TARGET_INDEX

	AL = CL;
	CH = [ESI];

	AL &= 3;
	++ESI;

	if (AL == 3)
		goto FORCE_21;

	CH &= 80H;
		JZ	NO_TARGET_INDEX
FORCE_21:
	++ESI;

NO_TARGET_INDEX	LABEL	PROC

	if (CL & 4)
		JNZ	LDI_LOOP

	// 2 OR 4
	ESI += EDX;
	// 19 VS 38
	goto LDI_LOOP;

HELP		LABEL	PROC

	// HERE COMES A THREAD DEFINITION, MUST BE PRESERVED....


	[EDI] = AL;
	// ANY INDEX?
	AL &= 5CH;
	++EDI;
	if (AL NC 50H)
		goto LDI_LOOP;
	// YES, ONE OR TWO BYTES?
	AL &= 0CH;
	AH = [ESI];
	++ESI;
	[EDI] = AH;
	++EDI;
	if (AL == 0CH)
		goto INC_TI;
	if (AL & 80H)
		JZ	LDI_LOOP
INC_TI:
	AH = [ESI];
	++ESI;
	[EDI] = AH;
	++EDI;
	goto LDI_LOOP;

DONE		LABEL	PROC

	// IF ANY THREADS, WRITE'M


	if (EDI != OFF NEW_FIXUPP)
		goto FIX_FIX;
NOTHING_HERE1::
	goto NOTHING_HERE;

}


FIX_FIX		LABEL	PROC

	// SET STUFF UP TO USE ABOVE CODE...


	ESI = OFF NEW_FIXUPP;
	END_OF_RECORD = EDI;

	EDX >>>= 1;
	EAX ^= EAX;

	--EDX;
	LAST_DATA_PTR = EAX;

	// 		MOV	FIX_LDATA_BLK,AX

	goto FIXUPP_CONTINUE;


public FIXUPP32()
{

	AL = MASK BIT_FI+MASK BIT_32;
	goto FIXUPP_COMMON;

public FIXUPP()
{

	AL = MASK BIT_FI;
    version(fg_phar)
    {
	AL |= BPTR DEFAULT_SIZE;
    }
FIXUPP_COMMON	LABEL	PROC



		PUSH	EBP
	EBP = ESP;

	ESP -= SIZE FIX_VARS;

	FIX_SIZE = AL;
	EAX ^= EAX;

	FIXUPP_COUNT = EAX;
	FIX_LOC = EAX;

	FIX_FRAME_STUFF.FS_TYPE = EAX;
	FIX_TARGET_STUFF.FS_TYPE = EAX;

	FIX_LDATA_BLK = EAX;

	// first we need to determine if this is a "keeper" record...


		GETT	AL,LAST_DATA_KEEP

	EDI = END_OF_RECORD;
	EDX = LAST_DATA_PTR;
		ASSUME	EDX:PTR LDATA_HEADER_TYPE

	if (AL & AL)
		JZ	SCAN_FOR_THREADS

	EDI -= ESI;
	// EMPTY FIXUPP, SKIP IT
		JZ	NOTHING_HERE1

	// NEED LAST_DATA


	AL = [EDX]._LD_TYPE;
		PUSH	ESI

	AL &= MASK BIT_CONT;
		JNZ	SPECIAL_LOAD

	EAX = &[EDX + SIZE LDATA_HEADER_TYPE];
	// PHYSICAL BLOCK # - FOR UNLOCKING
	FIX_LDATA_BLK = EDX;

	FIX_LDATA_PTR = EAX;
	goto LOAD_DONE;


SPECIAL_LOAD	LABEL	PROC

	// THIS GUY IS SPLIT OVER TWO BLOCKS, MOVE HIM TO LOCAL STORAGE


	ESI = EDX;
	ECX = SIZE LDATA_HEADER_TYPE/4;

	EDI = OFF TEMP_DATA_RECORD;
	// DATA LENGTH
	EBX = DPTR [EDX]._LD_LENGTH;

		REP	MOVSD

	// NEXT LOGICAL BLOCK #
	ECX = [EDX]._LD_BLOCK_BASE;
	FIX_LDATA_PTR = EDI;

	EAX = ECX;
	ECX += PAGE_SIZE;

	ECX -= ESI;
	EBX &= 0FFFFH;

	// SAVE THIS #
	EBX -= ECX;
	ECX >>>= 2;

		REP	MOVSD

	ECX = &[EBX+3];
	ESI = [EAX+4];

	ECX >>>= 2;
	ESI += BLOCK_BASE;

		REP	MOVSD

	// NO BLOCK TO UNLOCK...
	FIX_LDATA_BLK = ECX;

		ASSUME	EDX:NOTHING

LOAD_DONE	LABEL	PROC

	// NOW SET UP STUFF TO BE USED BY EXECUTE


	EAX = FIX_LDATA_PTR;
	ESI = LDATA_SEGMOD_GINDEX;
		CONVERT	ESI,ESI,SEGMOD_GARRAY

	EAX += LDATA_LENGTH;
	ECX = (SIZE SEGMOD_STRUCT+3)/4;

	FIX_END_OF_RECORD = EAX;
	EDI = &FIX_SEGMOD_STUFF;

		REP	MOVSD

	EAX = FIX_SEGMOD_STUFF._SM_BASE_SEG_GINDEX;
	FIX_OS2_FLAGS = ECX;

	FIX_LDATA_SEGMENT_GINDEX = EAX;
    version(fg_segm)
    {
	FIX_SKIP_PENTS = CL;

	FIX_COMDAT_PENTS = CL;
    }
	if (EAX & EAX)
		JZ	NO_BASE_SEG
		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

	DL = FIX_SEGMOD_STUFF._SM_FLAGS;
	ECX = [EAX]._SEG_OS2_FLAGS;

	EAX = [EAX]._SEG_GROUP_GINDEX;
		ASSUME	EAX:NOTHING
	FIX_OS2_FLAGS = ECX;

	DL &= MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1;
		JNZ	YSP
    version(fg_segm)
    {
	// CANNOT SKIP IF REALMODE
	if (PROTMODE)
		JZ	NSP

	// IF PROTMODE, ONLY DO THIS IF CURRENT SEGMENT IS NOT IOPL-NONCONFORMING-CODE


	ECX = FIX_LDATA_SEGMENT_GINDEX;
	EDX = FIX_OS2_FLAGS;

	// WE DON'T KNOW SEGMENT, DO IT
	if (ECX & ECX)
		JZ	NSP

	// CONFORMING OR DATA, CANNOT SKIP
	if (EDX & MASK SR_CONF+1)
		JNZ	NSP

	// NOT IOPL, CANNOT SKIP
	EDX &= 1 SHL SR_DPL;
		JZ	NSP
    }
YSP:
	FIX_SKIP_PENTS = -1;
NSP:
NO_BASE_SEG:
	FIX_LDATA_GROUP_GINDEX = EAX;

	// CALCULATE FIX_COMDAT_PENTS


	if (ENTRIES_POSSIBLE)
		JZ	NCP
	if (LAST_DATA_COMDAT)
		JZ	NCP

	// THIS IS ONE OF TWO CASES:


	// 	1. UNREFERENCED COMDATS - WE WILL DECREMENT PENT COUNTS IF NEVER REFERENCED

	// 	2. REFERENCED BUT NO KNOWN SEGMENT - WE WILL ADJUST IF PROTMODE AND IOPL


	if (REFERENCE_FLAGS == MASK S_SOFT_REF)
		goto YCP;
	if (FIX_LDATA_SEGMENT_GINDEX != 0)
		goto NCP;
	if (PROTMODE)
	// WE KEEP ALL IN REAL MODE
		JZ	NCP
YCP:
	FIX_COMDAT_PENTS = -1;
NCP:
		POP	ESI
	EDI = END_OF_RECORD;

FIXUPP_CONTINUE	LABEL	PROC

	EDI -= ESI;
		JZ	NOTHING_HERE

	FIX_NEW_PTR = OFF NEW_FIXUPP;
    version(fg_norm_exe OR fg_segm)
    {
	FIX_FARCALL_PTR = OFF FARCALL_FIXUPP;
    }
	PRE_FIXUPPS();

	RELEASE_LDATA_RECORD();

	FLUSH_NEWFIXUPP();
    version(fg_norm_exe OR fg_segm)
    {
	FLUSH_FARCALL();
    }
NOTHING_HERE	LABEL	PROC

	UPDATE_FIXUPP_COUNT();

	ESP = EBP;
		POP	EBP
	return;

}


UPDATE_FIXUPP_COUNT()
{



	ECX = FIXUPP_COUNT;
	EAX = LDATA_SEGMOD_GINDEX;

	if (ECX & ECX)
		JZ	FGP_9

	// CODEVIEW IGNORED?
	if (EAX & EAX)
		JZ	FGP_9

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

	[EAX]._SM_RELOC_CNT += ECX;
FGP_9:
	return;

}

		ASSUME	EAX:NOTHING


RELEASE_LDATA_RECORD()
{



	EAX = FIX_LDATA_BLK;
	EDI = LAST_DATA_PTR;

	if (EAX & EAX)
		JZ	L1$
L0$:
	return;

L1$:

	// MUST COPY BACK TO VIRTUAL SPACE


	if (EDI & EDI)
	ESI = OFF TEMP_DATA_RECORD;
		ASSUME	ESI:PTR LDATA_HEADER_TYPE

	ECX = SIZE LDATA_HEADER_TYPE/4;
		JZ	L0$

	EBX = ESI;
		ASSUME	EBX:PTR LDATA_HEADER_TYPE
	EAX = [ESI]._LD_BLOCK_BASE;

		REP	MOVSD

	// DATA LENGTH
	EBX = DPTR [EBX]._LD_LENGTH;
	ECX = EAX;

	EBX &= 0FFFFH;
	// BLOCK SIZE
	ECX += PAGE_SIZE;

	ECX -= EDI;

	// SAVE THIS #
	EBX -= ECX;
	ECX >>>= 2;

		REP	MOVSD

	ECX = &[EBX+3];
	EDI = [EAX+4];

	ECX >>>= 2;
	EDI += BLOCK_BASE;

		REP	MOVSD

	return;

}

		ASSUME	ESI:NOTHING,EBX:NOTHING


FLUSH_NEWFIXUPP()
{



	ESI = OFF NEW_FIXUPP;
	ECX = FIX_NEW_PTR;

	ECX -= ESI;
		JZ	L9$

	FIX_NEW_PTR = ESI;
	EDX = LAST_DATA_PTR;

	EDI = ECX;
	EAX = &[ECX + SIZE FIXUPP_HEADER_TYPE];

	CL = FIX_SIZE;
		PUSH	EDX

		PUSH	ECX
SPEC_RET:
	// EAX = BLOCK_BASE, ECX PHYS
	FIXUPP_ALLOC();
		JC	SPECIAL
	EDX = EDI;
SPEC_2:
		ASSUME	ECX:PTR FIXUPP_HEADER_TYPE

	[ECX]._FH_BLOCK_BASE = EAX;

	EAX ^= EAX;
	// SAVE OFFSET TOO
	LAST_DATA_PTR = ECX;

	// NEXT_LDATA

	// TYPE

	// SECOND_BLK

	// LENGTH


	[ECX]._FH_NEXT_FIXUPP = EAX;
	AL = FIX_SIZE;

	EAX <<= 16;
	EAX |= EDI;
	DPTR [ECX]._FH_LENGTH = EAX;

	// SECOND BLOCK
	EAX = EBX;
	// # OF BYTES
	EBX = EDI;
	// DESTINATION
	EDI = &[ECX+ SIZEOF FIXUPP_HEADER_TYPE];
	// # IN FIRST BLOCK
	ECX = EDX;
	// SECOND BLOCK
	EDX = EAX;

	LEDATA_CONT();

		POPM	ECX,EAX

	FIX_SIZE = CL;
	LAST_DATA_PTR = EAX;
L9$:
	return;

SPECIAL:
	// I WANT HEADER MINIMUM
	EDX -= SIZE FIXUPP_HEADER_TYPE;
		JC	SPEC1

	// HARD ONE, SET UP STUFF FOR DOING IT CORRECTLY...


		PUSHM	EAX,ECX,EDX
	FIX_SIZE |= MASK BIT_CONT;

	EAX = EDI;
	LAST_DATA_PTR = ECX;

	// NEED THIS MANY MORE
	EAX -= EDX;
	// GET MORE...
	LDATA_ALLOC();

		POP	EDX
	EBX = ECX;

		POPM	ECX,EAX

	goto SPEC_2;

SPEC1:

	// CANT EVEN FIT HEADER, RELEASE THIS


	// DON'T COUNT THAT GUY
	--DPTR [EAX];
	EAX = &[EDI+SIZE FIXUPP_HEADER_TYPE];
	goto SPEC_RET;

}


FLUSH_FARCALL()
{



	ESI = OFF FARCALL_FIXUPP;
	ECX = FIX_FARCALL_PTR;

	FIX_FARCALL_PTR = ESI;
	ECX -= ESI;

	EDI = ECX;
		JZ	L9$

	EAX = &[ECX + SIZE FARCALL_HEADER_TYPE];
FAR_SPEC_RET:
	// EAX=BLK BASE, ECX IS PHYS
	FARCALL_ALLOC();
		JC	FAR_SPECIAL

	EDX ^= EDX;
		ASSUME	ECX:PTR FARCALL_HEADER_TYPE

	// NEXT_FARCALL

	// SEGMENT

	// LENGTH


	EBX = EDI;

	[ECX]._FC_BLOCK_BASE = EAX;
	[ECX]._FC_NEXT_FARCALL = EDX;

	EAX = LDATA_SEGMOD_GINDEX;
	[ECX]._FC_LENGTH = EDI;

	[ECX]._FC_SEGMOD_GINDEX = EAX;
	EDI = &[ECX + SIZE FARCALL_HEADER_TYPE];

	EAX = ECX;
	ECX = &[EBX+3];

	// NOW MOVE REST OF FIRST BLOCK


	ECX >>>= 2;
	EDX = LAST_FARCALL;

		REP	MOVSD

	// NOW, LINK THIS TO FARCALL_LIST


	if (EDX & EDX)
		JZ	FIRST_FARCALL_

	[EDX].FARCALL_HEADER_TYPE._FC_NEXT_FARCALL = EAX;
FF_RET:
	LAST_FARCALL = EAX;
L9$:
	return;

FAR_SPECIAL:
	--DPTR [EAX];
	EAX = &[EDI + SIZE FARCALL_HEADER_TYPE];
	goto FAR_SPEC_RET;


FIRST_FARCALL_:
	FIRST_FARCALL = EAX;
	goto FF_RET;

}

		ASSUME	ECX:NOTHING


DO_THREAD()
{

	// HERE FOR DEFINING A NEW THREAD...


	// 	BIT

	//   7  6  5  4  3  2  1  0

	//   0  D  0   METHOD  THRED


	// WHERE  D=0 = TARGET

	// 	D=1 = FRAME


	// I WANT BX TO BE D:METHOD IN BITS 4-1

	// I WANT DI TO BE D:THRED IN BITS 5-3

	// I WANT AX TO BE METHOD IN BITS 3-1


	// IF D = 0, METHOD=METHOD MOD 4


	EAX &= 7FH;

	ECX = EAX;
	EDX = EAX;

	AL >>>= 2;
	// CL IS JUST D BIT
	ECX &= 40H;

	// DL IS THREAD
	EDX &= 3;
	// AL IS METHOD
	AL &= 7;

	CL >>>= 3;
	EDX += EDX;

	// EBX IS METHOD
	EBX = EAX;
	// EAX IS D:METHOD
	AL |= CL;

	DL |= CL;
	if (CL & CL)

		JNZ	DT_1

	EBX &= 3;
DT_1:
	EDI = &PRE_THREADS[EDX*8];
	BUFFER_OFFSET = ESI;

	CL = -1;

	[EDI] = EBX;
	BPTR [EDI+8] = CL;

	EDI += 4;
	switch (EAX)
	{
		DD	T_SEGMENT
		DD	T_GROUP
		DD	T_EXTERNAL
		DD	T_ABSOLUTE
		DD	T_SEGMENT
		DD	T_GROUP
		DD	T_EXTERNAL
		DD	T_ABSOLUTE
		DD	F_SEGMENT
		DD	F_GROUP
		DD	F_EXTERNAL
		DD	F_ABSOLUTE
		DD	F_OTHERS	// F_LOC (PROCESS LATER)
		DD	F_OTHERS	// F_TARG (PROCESS LATER)
		DD	F_BAD
		DD	F_BAD
	}
}


PRE_FIXUPPS()
{
	// 			ES MUST BE DGROUP HERE!

	if (END_OF_RECORD BE ESI)
		goto DONE_FIXUPPS;

	AL = [ESI];
	++ESI;

	if (AL & 80H)
	// THREAD DEFINITION
		JZ	DO_THREAD

	// HERE COMES THE REAL FIXUPPS


	AH = AL;
	AL >>>= 2;
    version(fg_phar)
    {
	// IF PHARLAP, CONVERT TO MS RECORD TYPE
	CL = BPTR DEFAULT_SIZE;
    }
	EAX &= 031FH;
    version(fg_phar)
    {
	if (CL & CL)
		JNZ	L1$
L19$:
    }
	// FIXUPP TYPE1
	BPTR FIX_LOC = AL;
	// EAX IS RECORD OFFSET
	AL = [ESI];

	// VERIFY RANGE FOR LDATA - MAKE SURE FIXUPP DOESN'T POINT PAST END OF RECORD


	EBX = LDATA_LENGTH;
	++ESI;

	EBX -= EAX;
		JC	BOUNDS_FAIL

	if (EBX $$ 6)
	FIX_OFFSET = EAX;

	EAX = FIX_LOC;
	// MUST DETERMINE LOC TYPE...
		JC	FURTHER_TESTING
FT_RET:
	// READ FRAME AND TARGET
	PRELIM();
		PUSH	ESI

	// NOW, SEE IF WE CAN REDUCE THE FRAME/TARGETS

	// VALID FRAME-TYPES ARE


	// 	0	SEGMENT FOLLOWS

	// 	1	GROUP FOLLOWS

	// 	2	EXTERNAL FOLLOWS

	// 	3	ABSOLUTE FOLLOWS

	// 	4	LOC		*

	// 	5	TARG		*

	// 	6	??

	// 	7	??

	// 	8	GROUP(LOC)	*

	// 	9	GROUP(TARG)	*

	// 	A	DGROUP

	// 	B	GROUP 1

	// 	C	GROUP 2


    version(fg_pe)
    {
	// PE OUTPUT IS FLAT, FRAME == TARG
		GETT	AL,OUTPUT_PE

	AL |= AL;
		JNZ	MCV_TARG
    }
	AL = FIX_SEGMOD_STUFF._SM_FLAGS;

	if (AL & MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1)
		JNZ	MCV_BASE
MCV_RET:
	EBX = FIX_FRAME_STUFF.FS_TYPE;
	ECX = FIX_FRAME_STUFF.FS_INDEX;

	EDX = FIX_TARGET_STUFF.FS_TYPE;
	EDI = FIX_TARGET_STUFF.FS_INDEX;

	switch (EBX)
	{
		DD	FRAME_SEGMENT
		DD	FRAME_OPTIMUM	// GROUP, NOTHING TO DO NOW...
		DD	FRAME_EXTERNAL
		DD	FRAME_ABSOLUTE
		DD	YES_LOC
		DD	FRAME_OPTIMUM	// TARG
		DD	FRAME_OPTIMUM	// BAD
		DD	FRAME_OPTIMUM	// BAD
	}

MCV_BASE:
		GETT	AL,CV_4_TYPE

	AL |= AL;
		JZ	MCV_RET
MCV_TARG:
	goto FRAME_TARG;

    version(fg_phar)
    {

L1$:
	// IF PHARLAP, CONVERT TO MS
	EBX = OFF PHAR_TO_MS;
		XLAT	[PHAR_TO_MS]
	goto L19$;

    }

PE:
	OBJ_PHASE();
	return;

DONE_FIXUPPS:
		JNZ	PE
	return;

FURTHER_TESTING:

	if (BL NC LOC_SIZE[EAX])
		goto FT_RET;
BOUNDS_FAIL:

	// ERROR...


	AL = FIXUPP_OFFSET_ERR;
	FIXUPP_ERROR();
	PRELIM();
	goto PRE_FIXUPPS;


FRAME_ABSOLUTE	LABEL	PROC

	// FRAME IS ABSOLUTE.  TO OPTIMIZE, TARGET MUST BE MATCHING

	// ABSOLUTE


	if (EDX != FS_TYPE_ASEG)
		goto FRAME_OPTIMUM;

	if (EDI == ECX)
		goto FRAME_TARG;
	goto FRAME_OPTIMUM;

FRAME_EXTERNAL	LABEL	PROC

	// FRAME IS AN EXTERNAL.  TO OPTIMIZE, TARGET MUST BE MATCHING

	// EXTERNAL


	if (EDX != FS_TYPE_SYMBOL)
		goto FRAME_OPTIMUM;

	if (EDI != ECX)
		goto FRAME_OPTIMUM;
FRAME_TARG:
	BPTR FIX_FRAME_STUFF.FS_TYPE = FS_TYPE_TARG;
FRAME_OPTIMUM::

	ESI = FIX_LOC;
	// THIS GUY HANDLES OFFSET-REDUCTION
	EXECUTE_FIXUPP();

	STORE_OPTIMAL();
OPTIMIZED_OUT:
		POP	ESI
	goto PRE_FIXUPPS;


FRAME_SEGMENT::

	// FRAME IS A SEGMENT.  TO OPTIMIZE, TARGET MUST BE MATCHING
	// SEGMENT, OR EXTERNAL IN SAME SEGMENT, OR LASTLY = LOCATION
	//   OR ASEG
	// 		MOV	BX,FIX_TARGET_STUFF.FS_TYPE

	switch (EDX)
	{
	    case 0:	// FRAME = SEG, TARG = SEG
		goto F_SEG_T_SEG;
	    case 1:	// FRAME = SEG, TARG = GROUP
		goto TRY_LOC;
	    case 2:	// FRAME = SEG, TARG = EXTERNAL
		goto F_SEG_T_EXT;
	    case 3:	// FRAME = SEG, TARG = ABSOLUTE
		goto TRY_LOC;
	}

F_SEG_T_EXT::
	// 		MOV	EDI,FIX_TARGET_STUFF.FS_INDEX

		CONVERT	EDI,EDI,SYMBOL_GARRAY
		ASSUME	EDI:PTR SYMBOL_STRUCT


	// SYMBOL MUST BE DEFINED, NO GROUP, SEGMENTS MATCHING


	AL = [EDI]._S_NSYM_TYPE;

	if (AL == NSYM_CONST)
		goto FRAME_TARG;

	if (AL A$ NSYM_RELOC)
		goto TRY_LOC;

	if (AL B$ NSYM_ASEG)
		goto TRY_LOC;

	AL = [EDI]._S_REF_FLAGS;
	EDI = [EDI]._S_SEG_GINDEX;

	if (AL & MASK S_USE_GROUP)
		JNZ	TRY_LOC
F_SEG_T_SEG::

	// BOTH ARE SEGMENTS, DO THEY MATCH?


FSTS_CONT:
		CONVERT	EDI,EDI,SEGMOD_GARRAY
		ASSUME	EDI:PTR SEGMOD_STRUCT

	// MUST MATCH BASE
	if ([EDI]._SM_BASE_SEG_GINDEX == ECX)
	// SEGMENT
		goto FRAME_TARG;
TRY_LOC::

	// TRY FOR 'LOC'


	if (FIX_LDATA_SEGMENT_GINDEX != ECX)
		goto FRAME_OPTIMUM;
YES_LOC::
	// LOC*2
	BPTR FIX_FRAME_STUFF.FS_TYPE = FS_TYPE_LOC;

	goto FRAME_OPTIMUM;

}

		ASSUME	EDI:NOTHING


STORE_OPTIMAL_MODEND()
{
	EDI = FIX_NEW_PTR + 4;
	EAX = 0x13 << 26;
	goto OPT_0;
}

STORE_OPTIMAL()
{
	// STORE OPTIMAL FIXUPP REPRESENTATION

	EAX = FIX_TARGET_STUFF.FS_TYPE;
	EDI = FIX_NEW_PTR;

	if (AL == -1)
		goto L9$;

	EAX = FIX_LOC;
	EDI += 4;

	EAX <<= 10;
	ECX = FIX_OFFSET;

	ESI = &FIX_TARGET_STUFF;
	EAX |= ECX;

	// LOC-TYPE AND OFFSET
	EAX <<= 16;
OPT_0::
	STORE_OPTI();

	FIX_NEW_PTR = EDI;
	if (EDI AE OFF NEW_FIXUPP+NEW_FIXUPP_SIZE-16)

		goto FLUSH_NEWFIXUPP;
L9$:
	return;

}


STORE_OPTI(THREAD_STUFF_STRUCT* ESI)
{
	// TARGET TYPE, 0=SEGMOD, 1=GROUP, 2=EXTERN, 3=ASEG
	AH = ESI.FS_TYPE;
	ECX = ESI.FS_INDEX;

	// OFFSET
	EDX = FIX_TOFFSET;
	// PLACE TO STORE THIS
	EBX = &[EDI-4];

	[EDI] = ECX;
	EDI += 4;

	if (EDX)
	{
	    [EDI] = EDX;
	    EDI += 4;
	    AH |= 10H;
	}

	// NOW DO FRAME

	// FRAME  0=SEG, 1=GRP, 2=EXT, 3=ASEG, 4=LOC, 5=TARG
	AL = BPTR FIX_FRAME_STUFF.FS_TYPE;
	ECX = FIX_FRAME_STUFF.FS_INDEX;

	if (AL <= 3)
	{
	    if (AL == 1)
	    {
		EDX = ECX.GROUP_STRUCT._G_NUMBER;
		if (EDX <= 16)
		{
		    EAX = &[EAX+EDX+5];
		    goto L6$;
		}
	    }
	    [EDI] = ECX;
	    EDI += 4;
	}
L6$:
	[EBX] = EAX;
	return;
}


EXECUTE_FIXUPP()
{
	// NOW SEE IF ANYONE CAN REDUCE OFFSET OR MAYBE COMPLETE FIXUP..

	// SAVE DS:SI

    version(alloc_support)
    {
	if (FIX_SEGMOD_STUFF._SM_FLAGS & MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1)
		JNZ	200$

	// HANDLE REFERENCES TO AN ALLOCATABLE SEGMOD

	// EXTERNAL?
	if (FIX_TARGET_STUFF.FS_TYPE != 4)
	// NO, TRY SEGMENT
		goto 2$;
		PUSHM	DS,SI
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		ASSUME	DS:NOTHING
		SYM_CONV_DS

	// BASICALLY, IF ASEG OR CONST OR IMPORT, IGNORE.  ELSE

	// PROCESS ACCESS BY THIS SEGMOD.


	// ALREADY REFERENCED
	if ([SI]._S_PLTYPE & MASK LEVEL_0_SECTION)
	// FROM LEVEL 0, IGNORE
		JNZ	19$

	// IF WE KNOW THIS SYMBOL WILL BE VECTORED, AND WE ARE NOT

	// ALLOCATING, THIS STUFF COULD ALL BE SKIPPED

	// .......

	SI = &_S_SECTION[SI];
		FIXES
	DI = &FIX_SEGMOD_STUFF._SM_SECTION;
	// DX:BX
	RETURN_LOWEST_SECTION();
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		SYM_CONV_DS
	if ([SI]._S_SECTION.OFFS == BX)
		goto 14$;
	[SI]._S_SECTION.OFFS = BX;
11$:
	[SI]._S_SECTION.SEGM = DX;
	DX |= DX;
		JZ	12$
	// SEE IF NOW LEVEL_0
	ES = DX;
		SYM_CONV_ES
	if (ES:[BX]._SECT_LEVEL != 0)
		goto 12$;
	[SI]._S_PLTYPE |= MASK LEVEL_0_SECTION;

	// WHAT ABOUT UPDATING THE SEGMOD, AND WHAT ABOUT OTHER PUBLICS
	// IN THAT SEGMOD?  AND WHAT THEN ABOUT RELEASING ANY OF THAT
	// STORAGE?

	// WE NEED TO UPDATE THE SEGMOD IFF IT IS ALLOCATABLE.
	// WELL, DON'T CARE ABOUT ANYTHING ELSE IF LEVEL 0 SECTION..

	goto 19$;

14$:
	if ([SI]._S_SECTION.SEGM != DX)
		goto 11$;
12$:

	// NOW, IF THIS SEGMOD IS ALLOCATABLE, ADD


	if (FIX_SEGMOD_STUFF._SM_PLTYPE & MASK SECTION_ASSIGNED)
	// NOT ALLOCATABLE
		JNZ	19$

	// ADD THIS SEGMOD TO LIST OF ALLOCATABLE SEGMODS REFERENCING

	// THIS SYMBOL


	DX = FIX_TARGET_STUFF.FS_PTR.SEGM;
	CX = FIX_TARGET_STUFF.FS_PTR.OFFS;
	AX = LDATA_SEGMOD.SEGM;
	BX = LDATA_SEGMOD.OFFS;
	INSTALL_PUBALLOC();
19$:
		POPM	SI,DS
191$:
	goto 3$;

2$:

	// IF AN ALLOCATABLE SEGMOD, PROCESS ACCESS BY 'THIS' SEGMOD


	// SEGMOD?
	if (FIX_TARGET_STUFF.FS_TYPE $$ 0)
200$:
		JNZ	191$

	// IGNORE IF SELF REFERENTIAL...


	AX = FIX_TARGET_STUFF.FS_PTR.OFFS;
	if (LDATA_SEGMOD.OFFS == AX)
		goto 28$;
20$:
		PUSHM	DS,SI
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		ASSUME	DS:NOTHING
		SYM_CONV_DS
	if ([SI]._SM_PLTYPE & MASK SECTION_ASSIGNED+MASK LEVEL_0_SECTION)
		JNZ	29$
	SI = &_SM_SECTION[SI];
		FIXES
	DI = &FIX_SEGMOD_STUFF._SM_SECTION;
	// DX:BX
	RETURN_LOWEST_SECTION();
		LDS	SI,FIX_TARGET_STUFF.FS_PTR
		SYM_CONV_DS
	if ([SI]._SM_SECTION.OFFS == BX)
		goto 24$;
	[SI]._SM_SECTION.OFFS = BX;
21$:
	[SI]._SM_SECTION.SEGM = DX;
	DX |= DX;
		JZ	22$
	// SEE IF NOW LEVEL_0
	ES = DX;
		SYM_CONV_ES
	if (ES:[BX]._SECT_LEVEL != 0)
		goto 22$;
	[SI]._SM_PLTYPE |= MASK LEVEL_0_SECTION;
	goto 29$;

24$:
	if ([SI]._SM_SECTION.SEGM == DX)
		goto 29$;
	goto 21$;

28$:
	AX = FIX_TARGET_STUFF.FS_PTR.SEGM;
	if (LDATA_SEGMOD.SEGM == AX)
		goto 3$;
	goto 20$;

22$:

	// NOW, IF THIS SEGMOD IS ALLOCATABLE, ADD


	if (FIX_SEGMOD_STUFF._SM_PLTYPE & MASK SECTION_ASSIGNED)
	// NOT ALLOCATABLE
		JNZ	29$

	// ADD THIS SEGMOD TO LIST OF ALLOCATABLE SEGMODS REFERENCING

	// THIS ALLOCATABLE SEGMOD...


	DX = FIX_TARGET_STUFF.FS_PTR.SEGM;
	CX = FIX_TARGET_STUFF.FS_PTR.OFFS;
	AX = LDATA_SEGMOD.SEGM;
	BX = LDATA_SEGMOD.OFFS;
	INSTALL_LIBALLOC();
29$:
		POPM	SI,DS
3$:
		ASSUME	DS:DGROUP
    }
	EAX = 0;
	EDI = FIX_LDATA_PTR;

	ECX = FIX_OFFSET;
    version(fg_segm)
    {
	LATEST_PENT_GINDEX = 0;
    }

	EDI += FIX_OFFSET;

	switch (ESI)
	{
	// 16-BIT SELF-RELATIVE
		DD	LOC_0
		DD	LOC_1
		REPT	3
		DD	BAD_LOC
		ENDM
		DD	BAD_LOC	// WAS PHARLAP_LOC_32
		DD	2 DUP(BAD_LOC)

	// 32-BIT SELF-RELATIVE
		DD	BAD_LOC
		DD	LOC_32SELF
		REPT	6
		DD	BAD_LOC
		ENDM

	// 16-BIT SEGMENT-RELATIVE
		DD	LOC_8
		DD	LOC_9
		DD	LOC_10_B
		DD	LOC_11
		DD	LOC_12
		DD	LOC_13	// WINDOWS-OS/2 SPECIAL
		DD	BAD_LOC	// WAS PHAR_FWORD_PTR
		DD	BAD_LOC

	// 32-BIT SEGMENT-RELATIVE
		DD	BAD_LOC
		DD	LOC_DWORD_OFFSET
		DD	LOC_DWORD_OFFSET	// TLS
		DD	LOC_FWORD_PTR
		DD	BAD_LOC
		DD	LOC_DWORD_OFFSET1
		DD	BAD_LOC
		DD	BAD_LOC
	}
}


void LOC_0()
{
	// SELF-RELATIVE SHORT JUMP
	// IF FRAME = TARG OR GROUP(TARG)
	//  AND TARGET = SEGMENT = LOC
	return;
}


LOC_1()
{
	// SELF-RELATIVE NEAR JUMP
	// CAN AT LEAST ADD IN OFFSET IF OFFSET IS NOT 32-BITS

	EAX = FIX_TOFFSET;
	ECX = 0;

	if (EAX C$ 64K)
		goto L1$;

	if (EAX A$ 0FFFF0000H)
		goto L9$;
L1$:
	WPTR [EDI] += AX;
	FIX_TOFFSET = ECX;

	// IF FRAME = TARG OR GROUP(TARG)
	//  AND TARGET = SEGMENT = LOC

	CHECK_SELF_REL();
		JNZ	L9$

	// YIPPEE! JUST SUBTRACT CURRENT LOCATION FROM ES:DI

	if (EAX & 0FFFF0000H)
		JNZ	L9$

	EAX += 2;
	CL = -1;

	WPTR [EDI] -= AX;
	// NO TARGET, IE, FIXUPP ELIMINATED
	BPTR FIX_TARGET_STUFF.FS_TYPE = CL;
L9$:
	return;
}


LOC_32SELF()
{
	// SELF-RELATIVE 32-BIT JUMP...
	// CAN AT LEAST ADD IN OFFSET

	EAX = [EDI];
	ECX = FIX_TOFFSET;

	EDX ^= EDX;
	EAX += ECX;

	FIX_TOFFSET = EDX;
	[EDI] = EAX;


	// IF FRAME = TARG OR GROUP(TARG)

	//  AND TARGET = SEGMENT = LOC


	CHECK_SELF_REL();
		JNZ	L9$

	EAX += 4;
	ECX = [EDI];

	ECX -= EAX;
	AL = -1;

	[EDI] = ECX;
	// NO TARGET, IE, FIXUPP ELIMINATED
	BPTR FIX_TARGET_STUFF.FS_TYPE = AL;
L9$:
	return;
}


CHECK_SELF_REL()
{



	AL = BPTR FIX_FRAME_STUFF.FS_TYPE;
	CL = BPTR FIX_TARGET_STUFF.FS_TYPE;

	// TARG*2
	if (AL != FS_TYPE_TARG)
	// NOPE, FAIL
		goto L9$;

	// SEGMENT*2
	if (CL != FS_TYPE_SEGMENT)
		goto L9$;

	ECX = FIX_TARGET_STUFF.FS_INDEX;
	EAX = LDATA_SEGMOD_GINDEX;

	if (EAX != ECX)
	// FAIL IF DIFFERENT SEGMOD
		goto L9$;

	// YIPPEE! JUST SUBTRACT CURRENT LOCATION FROM ES:DI


	// OK, SO, FIX_TOFFSET-CURLOC-4


	EAX = LDATA_LOC;
	ECX = FIX_OFFSET;

	EAX += ECX;
	if (EBX $$ EBX)
L9$:
	return;

}


LOC_8()
{
	// LO-BYTE
	CHECK_ASEG_OFFSET();
	ECX = FIX_TOFFSET;
		JNZ	L9$
	EAX += ECX;
	CL = [EDI];
	if (EAX BE 255)
		goto L8$;
	if (EAX NC -128)
		goto L8$;
L9$:
	return;

L8$:
	CL += AL;
	AL = -1;

	[EDI] = CL;
	BPTR FIX_TARGET_STUFF.FS_TYPE = AL;

	return;
}


LOC_12()
{
	// HIGH BYTE

	CHECK_ASEG_OFFSET();

	ECX = FIX_TOFFSET;
		JNZ	L9$

	DL = [EDI];
	EAX += ECX;

	CL = -1;
	DL += AH;

	// FIXUPP COMPLETED
	BPTR FIX_TARGET_STUFF.FS_TYPE = CL;
	[EDI] = DL;

L9$:
	return;
}


LOC_9()
{
	// 16-BIT OFFSET
	// CAN AT LEAST GET RID OF OFFSET IF NOT 32-BIT
	// IF TARG = ABSOLUTE, CAN COMPLETELY PROCESS PROBABLY...

	EAX = FIX_TOFFSET;
	ECX ^= ECX;

	if (EAX NC -64K)
		goto L2$;

	if (EAX NC 64K)
		goto L9$;
L2$:
	WPTR [EDI] += AX;
	FIX_TOFFSET = ECX;

	CHECK_ASEG_OFFSET();
	CL = -1;
		JNZ	L9$

	WPTR [EDI] += AX;
	// FIXUPP COMPLETED
	BPTR FIX_TARGET_STUFF.FS_TYPE = CL;
L9$:
	return;

}


LOC_13()
{

	// 16-BIT OFFSET, LOADER MODIFIED


    version(fg_segm)
    {

	// NEED TO DETERMINE IF PENT IS NECESSARY


LOC_130::
		GETT	AL,ENTRIES_POSSIBLE

	AL |= AL;
		JZ	LOC_9

	LOC_9();
	// FROM DWORD SPECIAL OFFSET
LOC_131::
	// 		XOR	CL,CL			;ASSUME SEGMENT

	// FROM BASE
LOC_132::



	AL = FIX_SKIP_PENTS;
	EBX = FIX_TARGET_STUFF.FS_TYPE;

	AL |= AL;
	// SKIP ALL IF DEBUG INFORMATION, IOPL-CONF-CODE, ETC
		JNZ	L9$

	if (BL == -1)
	// SKIP IF FULLY PROCESSED (ASEGS, CONSTANTS, NEAR CALLS)
		goto L9$;

	// SEGMOD, GROUP, SYMBOL, ASEG
	EDX = FIX_TARGET_STUFF.FS_INDEX;
	JMP_TABLE[EBX*4]();
L9$:
ASEG_13:
RETT:
	return;


	// UNDER WHAT CONDITIONS MAY I NOT BOTHER WITH PENT
	// 	FOR GROUPS, GROUP TYPE MUST BE ASEG, RARE, SO I WILL NOT BOTHER CHECKING, JUST INSTALL
	// 		(WILL ALMOST ALWAYS BE DGROUP:0, BUT DO IT ANYWAY).
	// 	FOR SEGMODS, AGAIN, TYPE MUST BE ASEG, OR FIXED, OR NOT IOPL IF PROTMODE
	// 		;;;;;CANNOT KNOW IF ITS A COMDAT, OTHERWISE I CAN BE QUITE SURE. -COMDATS MUST BE REFERENCED AS SYMS
	// 	FOR EXTERNALS, CAN IGNORE IF ASEG OR CONST OR IMPORT OR FLOAT_SYM.  IF RELOC, TEST SEGMOD AS ABOVE,
	// 		 BUT STORE AS SYMBOL
	// 	FOR ASEG, SIMPLY IGNORE
	// ALL OTHERS MUST ASSUME POSSIBLE ENTRY POINT


GROUP_13:
	CL = 2;
	goto STORE_INDEX;

SEGMOD_13:

	// IF ASEG, SKIP IT

	// DON'T BOTHER, NOT LIKELY IN SEGMENTED MODE...


	// INSTALL SEGMOD-OFFSET INTO TABLE


	// 0=SEGMENT
	CL = 0;
STORE_INDEX:

	// SEGMOD, GROUP, SYMBOL INDEX IN DX


	EBX = FIX_TOFFSET;

		MOVSX	EAX,WPTR [EDI]

	ECX &= 0FH;
	EAX += EBX;

	// EDX IS GINDEX

	// EAX IS OFFSET FROM ABOVE

	// ECX IS TYPE


	INSTALL_PENT();
	DL = FIX_COMDAT_PENTS;

	// IN CERTAIN CASES, WE MUST KEEP TRACK OF THESE
	DL |= DL;
		JNZ	SI_1

	return;

SI_1:

	// THIS IS ONE OF TWO CASES:

	// 	1. UNREFERENCED COMDATS - WE WILL DECREMENT PENT COUNTS IF NEVER REFERENCED
	// 	2. REFERENCED BUT NO KNOWN SEGMENT - WE WILL ADJUST IF PROTMODE AND IOPL


	INSTALL_SOFT_PENT();
	return;

EXTERNAL_13:
		CONVERT	EAX,EDX,SYMBOL_GARRAY
		ASSUME	EAX:PTR SYMBOL_STRUCT

	BL = [EAX]._S_REF_FLAGS;

	BL &= MASK S_FLOAT_SYM;
		JNZ	RETT

	AL = [EAX]._S_NSYM_TYPE;
	CL = 1;

	if (AL == NSYM_ASEG)
		goto RETT;

	if (AL == NSYM_CONST)
		goto RETT;

	if (AL != NSYM_IMPORT)
		goto STORE_INDEX;

	return;

		ASSUME	EAX:NOTHING

ife	data_in_codeseg

		.DATA

    }

		ALIGN	4

JMP_TABLE	DD	SEGMOD_13,GROUP_13,EXTERNAL_13,ASEG_13


ife	data_in_codeseg

		.CODE	PASS1_TEXT

    }


    }
    else
    {

LOC_130:
	goto LOC_9;

    }

}


CHECK_ASEG_OFFSET()
{
	// IF TARG = CONSTANT OR TARG = SEGMENT AT

	AL = BPTR FIX_FRAME_STUFF.FS_TYPE;
	CL = BPTR FIX_TARGET_STUFF.FS_TYPE;

	// MUST BE FRAME(TARG)
	if (AL != FS_TYPE_TARG)
		goto L9$;

	// EXTRN
	if (CL != FS_TYPE_SYMBOL)
		goto L9$;

	AL = FIX_NSYM_TYPE;
	ECX = FIX_TARGET_STUFF.FS_INDEX;

	if (AL != NSYM_CONST)
		goto L9$;

		CONVERT	ECX,ECX,SYMBOL_GARRAY
		ASSUME	ECX:PTR SYMBOL_STRUCT

    version(fg_segm)
    {
	DL = [ECX]._S_REF_FLAGS;
    }
	EAX = [ECX]._S_OFFSET;

    version(fg_segm)
    {
	DL &= MASK S_FLOAT_SYM;
		JNZ	EXT1
    }
    else
    {
	if (ECX $$ ECX)
    }

L9$:
	return;

GROUP_1:
	AL |= -1;
	return;

    version(fg_segm)
    {
EXT1:
		GETT	DL,OUTPUT_SEGMENTED
	AL = BPTR [ECX]._S_FLOAT_TYPE;

	DL |= DL;
	// BETTER NOT, MAY TURN SEGMENTED LATER...
		JZ	GROUP_1

	EAX &= 7;
	return;
    }

}


LOC_11()
{
	// 16:16 POINTER

	EAX = FIX_TARGET_STUFF.FS_TYPE;
		PUSH	EAX
	// SPECIAL 16-BIT OFFSET - DOES ENTRY EVEN IF PROTMODE
	LOC_130();
		POP	EAX
	ECX = FIX_OFFSET;

	// POSSIBILITY CHECK...
	EDI += 2;
	ECX += 2;

	FIX_TARGET_STUFF.FS_TYPE = EAX;
	FIX_OFFSET = ECX;

	// PLUS WHATEVER ELSE IS NEEDED FOR RANGE CHECKING


	// NO PENT
	LOC_10_A();
	ECX = FIX_OFFSET;
	AL = FIX_NSYM_TYPE;

	ECX -= 2;
	if (AL $$ NSYM_CONST)

	FIX_OFFSET = ECX;
		JNZ	L5$

	AL = BPTR FIX_TARGET_STUFF.FS_TYPE;
	CL = -1;

	if (AL != FS_TYPE_SYMBOL)
		goto L5$;

	BPTR FIX_TARGET_STUFF.FS_TYPE = AL;
L5$:
    version(fg_norm_exe OR fg_segm)
    {

	// WHAT IF REALMODE, FARCALLTRANSLATE, AND NO EXEPACK?

	// OR, ENTRIES_POSSIBLE AND FARCALLTRANSLATE


	goto LOC_11_FIX;
    }
public LOC_11_DONE::
	return;

}


    version(fg_norm_exe OR fg_segm)
    {

LOC_11_R()
{

	// MAYBE REAL MODE, FARCALLTRANSLATE SELECTED, NO EXEPACK

	// OR SEGMENTED, REALMODE, FARCALLTRANSLATE, PENT


	CL = FIX_SKIP_PENTS;
	AL = CLASS_TYPE;

	CL |= CL;
		JNZ	LOC_11_DONE

	if (AL & MASK SEG_CLASS_IS_CODE)
		JZ	LOC_11_DONE

	AL = FIX_SEGMOD_STUFF._SM_FLAGS_2;
	ECX = FIX_OFFSET;

	if (AL & MASK SM2_DATA_IN_CODE)
		JNZ	LOC_11_DONE

	// IF ZERO, WE CANNOT TELL IF ITS A
	ECX |= ECX;
	// FAR CALL OR WHAT...
		JZ	LOC_11_MAYBE
LOC_11_M_RET:

	// FARCALL?


	AL = BPTR [EDI-3];

	if (AL == 0EAH)
		goto LOC_11_YES;

	if (AL == 9AH)
		goto LOC_11_YES;
	goto LOC_11_DONE;

LOC_11_MAYBE:

	// WE ARE AT OFFSET ZERO IN THE RECORD, IS THE PREVIOUS RECORD

	// USABLE?


	// PREVIOUS RECORD VALID?
	EDX = PREV_DATA_PTR;
		ASSUME	EDX:PTR LDATA_HEADER_TYPE
	ECX = [EDI + (LDATA_HEADER_TYPE._LD_OFFSET-SIZE LDATA_HEADER_TYPE)-2];

	if (EDX & EDX)
		JZ	LOC_11_DONE

	// DISTANCE TO CURRENT RECORD FROM BEGINNING OF PREVIOUS
	ECX -= [EDX]._LD_OFFSET;
	// NOPE...PREVIOUS IS LOGICALLY AFTER CURRENT
		JC	LOC_11_DONE

	// PREVIOUS REACHES AT LEAST FAR ENOUGH?
	if ([EDX]._LD_LENGTH C$ CX)
	// NOPE
		goto LOC_11_DONE;




	// 		MOV	AX,ES:[DI]._LD_SECOND_BLK	;IN CASE RECORD SPLITS BLOCKS...
	// 		ADD	DI,CX
	// 		ADD	DI,SIZE LDATA_HEADER_TYPE+2	;ADDRESS WE WILL LOOK BACK 3 FROM FOR JMP OR CALL
	// 		CMP	DI,PAGE_SIZE+3			;WILL -3 STILL BE IN BLOCK?
	// 		JC	LOC_11_M_RET			;YES, JUMP
	// 		SUB	DI,PAGE_SIZE-2			;ADJUST BY BLOCK SIZE ALLOWING FOR WORD COUNT AT START OF EACH BLOCK


	goto LOC_11_M_RET;

LOC_11_YES:
	AL = BPTR FIX_TARGET_STUFF.FS_TYPE;
	ESI = &FIX_TARGET_STUFF;
	// OPTIMIZED AWAY?
	if (AL == -1)
		goto LOC_11_DONE;
	EDI = FIX_FARCALL_PTR;
	EAX ^= EAX;
	EDI += 4;
	STORE_OPTI();
    version(fg_segm)
    {
		GETT	CL,ENTRIES_POSSIBLE
	EAX = LATEST_PENT_GINDEX;
	CL |= CL;
		JZ	L6$
	[EDI] = EAX;
	EDI += 4;
L6$:
    }
	FIX_FARCALL_PTR = EDI;
	if (EDI AE OFF FARCALL_FIXUPP+INBUF_LEN-13)
		goto L7$;
	return;

L7$:
	FLUSH_FARCALL();
	return;

}

    }


LOC_DWORD_OFFSET1()
{
    version(fg_segm)
    {

LOC_DWORD_OFFSET2::
	// IF PROTMODE, MUST BE IOPL
		GETT	AL,ENTRIES_POSSIBLE

	if (AL & AL)
	// FOR REAL, MUST BE MOVEABLE
		JZ	LOC_DWORD_OFFSET

	LOC_DWORD_OFFSET();
	goto LOC_131;

    }
    else
    {

LOC_DWORD_OFFSET2::

    }

}


LOC_DWORD_OFFSET()
{
	ECX = [EDI];
	EAX = FIX_TOFFSET;

	EDX ^= EDX;
	EAX += ECX;

	FIX_TOFFSET = EDX;
	[EDI] = EAX;

	// CAN WE DO MORE?
	CHECK_ASEG_OFFSET();

	ECX = [EDI];
		JNZ	L9$

	EAX += ECX;
	CL = -1;

	[EDI] = EAX;
	// FIXUPP COMPLETED
	BPTR FIX_TARGET_STUFF.FS_TYPE = CL;
L9$:
	return;

}


LOC_FWORD_PTR()
{
	EAX = FIX_TARGET_STUFF.FS_TYPE;

		PUSH	EAX
	// DOES PENT
	LOC_DWORD_OFFSET2();

	ECX = FIX_OFFSET;
		POP	EAX

	ECX += 4;
	FIX_TARGET_STUFF.FS_TYPE = EAX;

	FIX_OFFSET = ECX;
	EDI += 4;

	// NO PENT
	LOC_10_A();

	FIX_OFFSET -= 4;
	return;

}


LOC_10_B()
{

	// BASE


    version(fg_segm)
    {
	// IF PROTMODE, MUST BE IOPL
		GETT	AL,ENTRIES_POSSIBLE

	AL |= AL;
	// FOR REAL, MUST BE MOVEABLE
		JZ	L1$
	LOC_132();
	goto L2$;

    }

L1$:
	// BASE OFFSET IS SIGNIFICANT IF ENTRIES POSSIBLE
	EAX ^= EAX;
	FIX_TOFFSET = EAX;
L2$:
LOC_10_A::

	// IF FRAME & TARG IS ASEG, WE ARE HOME FREE, JUST STORE IT...


	// IF RELOCATABLE OR UNDEFINED, NEED TO COUNT IT AS A FIXUP

	// IF LIDATA, NEEDS SPECIAL PROCESSING


	// ITS NOT LIKELY THAT WE WILL DO FULL REDUCTION, SO DON'T BOTHER EVEN LOOKING IF WE DON'T NEED A RELOC COUNT...


    version(fg_norm_exe)
    {
    version(fg_pe OR fg_segm)
    {
		GETT	AL,OUTPUT_PE
		GETT	CL,OUTPUT_SEGMENTED

	AL |= CL;
	// DON'T BOTHER COUNTING...
		JNZ	L9$
    }

	// COM OR SYS
		GETT	AL,OUTPUT_COM_SYS
	// NOT IF EXEPACKED EITHER...
		GETT	CL,EXEPACK_SELECTED

	AL |= CL;
		JNZ	L9$
    version(fg_slrpack)
    {
	// ANY KIND OF PACKING MEANS DON'T COUNT EM
		GETT	AL,SLRPACK_FLAG

	AL |= AL;
		JNZ	L9$
    }

	// SKIP IT IF IT IS A DEBUG RECORD...


	AL = FIX_SEGMOD_STUFF._SM_FLAGS;
	EBX = FIX_TARGET_STUFF.FS_TYPE;

	if (AL & MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1)
		JNZ	L9$

	// OK, TRY TO ELIMINATE THIS


	EAX = FIX_TARGET_STUFF.FS_INDEX;
	switch (EBX)
	{
		DD	L10_TSEG
		DD	L10_TGRP
		DD	L10_TEXT
		DD	L10_DOFRAME	// ASEG, NOT SUPPORTED BY MS
	}

L10_TSEG::

	// TARGET IS A SEGMENT

	// IF ASEG, REPLACE, ELSE COUNT IT


		CONVERT	EAX,EAX,SEGMOD_GARRAY
	AL = [EAX].SEGMOD_STRUCT._SM_FLAGS;

	if (AL & MASK SEG_ASEG)
		JZ	L10_RELOC
	goto L10_SKIP_FRAME;


L10_TGRP::

	// TARGET IS GROUP,


		CONVERT	EAX,EAX,GROUP_GARRAY
	AL = [EAX].GROUP_STRUCT._G_TYPE;

	if (AL & MASK SEG_ASEG)
	// CAN'T RESOLVE, BUT ASEG...
		JZ	L10_RELOC
	goto L10_SKIP_FRAME;

L10_TEXT::

	// TARGET IS A SYMBOL

	// IF ABSOLUTE, TRY REPLACING IT


		CONVERT	EAX,EAX,SYMBOL_GARRAY
	BL = [EAX].SYMBOL_STRUCT._S_NSYM_TYPE;

	if (BL == NSYM_CONST)
		goto L10_SKIP_FRAME;

	if (BL == NSYM_ASEG)
		goto L10_SKIP_FRAME;
L10_RELOC:

	// ALL OF THIS JUST TO ESTIMATE SIZE OF EXEHDR


	// ASSUMING IT IS RELOCATABLE...


	ECX = FIXUPP_COUNT;
	AL = LDATA_TYPE;

	++ECX;
	// LI OR LE
	if (AL & MASK BIT_LI)

	FIXUPP_COUNT = ECX;
		JZ	L9$

	LIBASE_PRELIM();
L9$:
	return;


L10_DOFRAME::
	if (FIX_FRAME_STUFF.FS_TYPE != FS_TYPE_TARG)
		goto L10_SKIP_FRAME;

	WPTR [EDI] += AX;
	BPTR FIX_TARGET_STUFF.FS_TYPE = -1;
L10_SKIP_FRAME:
	return;

    }
    else
    {

	return;
    }

}


BAD_LOC()
{

	AL = UNREC_FIXUPP_ERR;
	FIXUPP_ERROR();
	return;

}


T_GROUP()
{

F_GROUP::
		NEXT_INDEX	TG_L

		CONVERT_LINDEX_EAX_EAX		GROUP_LARRAY,EDX

	[EDI] = EAX;

	return;

		DOLONG	TG_L

}


T_EXTERNAL()
{
F_EXTERNAL::
		NEXT_INDEX	TE_L
	ECX = EXTDEF_DELTA;

	EAX += ECX;
		CONVERT_LINDEX_EAX_EAX	SYMBOL_LARRAY,EDX
T_EXTERNAL_VIRDEF::
	[EDI] = EAX;
		CONVERT	EDX,EAX,SYMBOL_GARRAY
		ASSUME	EDX:PTR SYMBOL_STRUCT

	// SAVE GINDEX
	ECX = EAX;
	// PROBABLY EITHER S_HARD_REF OR S_SOFT_REF
	AL = REFERENCE_FLAGS;

	BL = [EDX]._S_REF_FLAGS;
	AH = FS_TYPE_TARG;

	AL |= BL;
	BL = [EDX]._S_NSYM_TYPE;

	[EDX]._S_REF_FLAGS = AL;
	if (AL & MASK S_FLOAT_SYM)

	FIX_NSYM_TYPE = BL;
		JNZ	ERF_2

	if (BL == NSYM_CONST)
		goto ERF_2;
ERF_3:
	if (AL & MASK S_REFERENCED+MASK S_HARD_REF)
		JZ	ERF_1

	return;

		DOLONG	TE_L

ERF_2:

	// CONSTANTS AND FLOAT SYMBOLS IGNORE FRAME STUFF, MAKE IT FRAME(TARG)


	// TARG*2
	BPTR FIX_FRAME_STUFF.FS_TYPE = AH;
	goto ERF_3;

ERF_1:

	// THIS SYMBOL HAS ONLY BEEN SOFT REFERENCED, MAKE SURE IT IS IN LIST FOR THIS COMDAT...


	EAX = ECX;
	goto INSTALL_SOFT_REF;

}


T_ABSOLUTE()
{
F_ABSOLUTE::
	AL = BPTR [ESI];

	AH = BPTR [ESI+1];
	ESI += 2;

	EAX &= 0FFFFH;

	// ABSOLUTE PARAGRAPH
	[EDI] = EAX;

	return;

}


T_SEGMENT()
{

		NEXT_INDEX	TS_L

	if (EAX A$ 16K)
		goto T_SEG_MVIRDEF;
L1$:
		CONVERT_LINDEX_EAX_EAX	SEGMOD_LARRAY,EDX
L2$:
	[EDI] = EAX;
T_OTHERS::
	return;

		DOLONG	TS_L

T_SEG_MVIRDEF:

	// INDEX >16K, MAYBE A BORLAND VIRDEF??


		CONVERT_MYCOMDAT_EAX_ECX
		ASSUME	ECX:PTR MYCOMDAT_STRUCT

	DL = [EDI-4];
		JC	L1$

	DL += FS_TYPE_SYMBOL-FS_TYPE_SEGMOD;
	EAX = [ECX]._MCD_SYMBOL_GINDEX;

	// CHANGE INDEX TYPE FROM SEGMOD TO EXTERNAL...


	[EDI-4] = DL;
	goto T_EXTERNAL_VIRDEF;

}


F_LOC()
{

	// WE WANT (TARG) IF POSSIBLE


	// FOR COMDAT...
	ECX = FIX_LDATA_SEGMENT_GINDEX;
	EAX = LDATA_SEGMOD_GINDEX;

	if (ECX & ECX)
		JZ	F_OTHERS

	if (EAX & EAX)
		JZ	BAD_THREAD1

	// MARK IT SEGMENT TYPE
	BPTR [EDI-4] = FS_TYPE_SEGMOD;

	goto F_SEG_1;

BAD_THREAD1:
	AL = BAD_LOC_ERR;
	ERR_ABORT();

}


F_SEGMENT()
{



		NEXT_INDEX	FS_L

	if (EAX A$ 16K)
		goto F_SEG_MVIRDEF;
L1$:
		CONVERT_LINDEX_EAX_EAX		SEGMOD_LARRAY,EDX
F_SEG_1::
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

	EAX = [EAX]._SM_BASE_SEG_GINDEX;

	[EDI] = EAX;
F_OTHERS::
F_TARG::
	return;

		ASSUME	EAX:NOTHING


		DOLONG	FS_L

F_SEG_MVIRDEF:

	// INDEX >16K, MAYBE A BORLAND VIRDEF??


		CONVERT_MYCOMDAT_EAX_ECX
		JC	L1$
	EAX = [ECX]._MCD_SYMBOL_GINDEX;

	// CHANGE INDEX TYPE FROM SEGMOD TO EXTERNAL...


	BPTR [EDI-4] += FS_TYPE_SYMBOL-FS_TYPE_SEGMOD;
	goto T_EXTERNAL_VIRDEF;

}


F_BAD::
	AL = UNRECOGNIZED_FIXUPP_FRAME_ERR;
	ERR_ABORT();


T_ABSOLUTE_OFFSET()
{
	T_ABSOLUTE();
	goto DO_OFFSET;

T_GROUP_OFFSET::
	T_GROUP();
	goto DO_OFFSET;

T_EXTERNAL_OFFSET::
	T_EXTERNAL();
	goto DO_OFFSET;

T_SEGMENT_OFFSET::
	T_SEGMENT();
DO_OFFSET::
	DL = FIX_SIZE;
	EAX = DPTR [ESI];

	DL &= MASK BIT_32;
		JZ	DO_OFFSET_16

	ESI += 4;
	FIX_TOFFSET = EAX;

	return;

DO_OFFSET_16:
	// NEED SIGN EXTENDED
		MOVSX	EAX,AX

	ESI += 2;
	FIX_TOFFSET = EAX;

	return;

}


F_T_0()
{



	EBX &= 3;

	EDX = &PRE_THREADS[EBX*8]+4*SIZE THREAD_STUFF_STRUCT;
		ASSUME	EDX:PTR THREAD_STUFF_STRUCT,EBX:NOTHING,EDI:NOTHING

	EAX = [EDX+EBX*8].FS_TYPE;
	ECX = [EDX+EBX*8].FS_INDEX;

	[EDI-4] = EAX;
	[EDI] = ECX;

	EAX = [EDX+EBX*8].FS_FILLER;
	EDI += 4;

	if (EAX & EAX)
		JZ	BAD_THREAD

	return;

BAD_THREAD:
	AL = BAD_THREAD_ERR;
	ERR_ABORT();

T_T_0::
	EBX &= 3;

	EDX = &PRE_THREADS[EBX*8];
		ASSUME	EDX:PTR THREAD_STUFF_STRUCT,EBX:NOTHING,EDI:NOTHING

	EAX = [EDX+EBX*8].FS_TYPE;
	ECX = [EDX+EBX*8].FS_INDEX;

	[EDI-4] = EAX;
	[EDI] = ECX;

	EAX = [EDX+EBX*8].FS_FILLER;
	EDI += 4;

	if (EAX & EAX)
		JZ	BAD_THREAD

	return;

T_T_0_OFFSET::
	T_T_0();
	goto DO_OFFSET;

}


public PRELIM()
{
	BL = *ESI++;

		PUSH	EBX

	BL >>>= 4;
	EDI = &FIX_FRAME_STUFF.FS_INDEX;

	EBX &= 0FH;
	BUFFER_OFFSET = ESI;

	FIX_FRAME_STUFF.FS_TYPE = EBX;

	// GET PROPER FRAME
	switch (EBX)
	{
		DD	F_SEGMENT(); break;
		DD	F_GROUP(); break;
		DD	F_EXTERNAL(); break;
		DD	F_ABSOLUTE(); break;
		DD	F_LOC(); break;
		DD	F_TARG(); break;
		DD	F_BAD(); break;
		DD	F_BAD(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
		DD	F_T_0(); break;
	}

		POP	EBX
	EDI = &FIX_TARGET_STUFF.FS_INDEX;

	EAX = EBX;
	EBX &= 0FH;

	EAX &= 3;
	ECX = 0;

	FIX_TARGET_STUFF.FS_TYPE = EAX;
	// ASSUME OFFSET = 0 ?
	FIX_TOFFSET = ECX;

	switch (EBX)
	{
		DD	T_SEGMENT_OFFSET
		DD	T_GROUP_OFFSET
		DD	T_EXTERNAL_OFFSET
		DD	T_ABSOLUTE_OFFSET
		DD	T_SEGMENT
		DD	T_GROUP
		DD	T_EXTERNAL
		DD	T_ABSOLUTE
		DD	T_T_0_OFFSET
		DD	T_T_0_OFFSET
		DD	T_T_0_OFFSET
		DD	T_T_0_OFFSET
		DD	T_T_0
		DD	T_T_0
		DD	T_T_0
		DD	T_T_0
	}
}


version(fg_norm_exe)
{

LIBASE_PRELIM()
{
	// JUST HANDLES 16-BIT RECORDS...

	AL = LDATA_TYPE;
		PUSH	EBX

	if (AL & MASK BIT_32)
		JNZ	L01$

	ESI = FIX_LDATA_PTR;
	// FOR QUICK RECOVERY
	FIX_ESP_SAVE = ESP;
L0$:
	L1$();

	if (FIX_END_OF_RECORD A$ ESI)
		goto L0$;
L01$:
	AL = LIDATA_ERR;
	ERR_ABORT();
	// ACTUALLY FAILURE...
	return;

L1$:
	// INITIAL REPEAT COUNT
	EDX = 1;
	// BLOCK COUNT
	ECX = 1;
L2$:
		PUSHM	EDX,ECX

		MOVZX	EAX,WPTR [ESI]
		MUL	EDX
		MOVZX	ECX,WPTR [ESI+2]

	EDX = EAX;
	ESI += 4;

	if (ECX & ECX)
		JZ	L5$

	L2$();
L4$:
		POPM	ECX,EDX

	--ECX;
		JNZ	L2$

	return;

L5$:
	CL = [ESI];
	ESI += ECX;

	++ESI;

	if (EDI NC ESI)
		goto L4$;

	--EDX;
	ESP = FIX_ESP_SAVE;

	FIXUPP_COUNT += EDX;
		POP	EBX

	return;

}

}


public FIXUPP_MODEND()
{
		PUSH	EBP
	EBP = ESP;
	ESP -= SIZE FIX_VARS;

	EAX = CURNMOD_GINDEX;
	FIX_SIZE = CL;
	MODEND_OWNER_GINDEX = EAX;

	FIX_NEW_PTR = OFF NEW_FIXUPP;
	// INVALIDATE 'LOC' FRAME TYPE
	LDATA_SEGMOD_GINDEX = 0;
	PRELIM();

	ESI = &FIX_TARGET_STUFF;
	STORE_OPTIMAL_MODEND();

	FIX_SIZE |= MASK BIT_ME;
	EAX = FIX_NEW_PTR;
	ESI = &NEW_FIXUPP;
	EAX -= ESI;
		JZ	L9$
	ECX = EAX;
	EAX += 4;
		TILLP2_POOL_ALLOC
	EDI = EAX;
	MODEND_ADDRESS = EAX;

	EAX = &[ECX];

	*EDI++ = EAX;

		REP	MOVSB
L9$:
	ESP = EBP;
		POP	EBP
	return;

}


		.CONST

public LOC_SIZE	LABEL	BYTE
	// 16-BIT SELF-RELATIVE

	// BYTE
		DB	1
	// WORD
		DB	2
		DB	3 DUP(1)
	// PHARLAP 32 SELF
		DB	4
		DB	2 DUP(1)
	// 32-BIT EQUIVALENTS OF ABOVE...

		DB	1
		DB	4
	// TLS
		DB	4
		DB	5 DUP(1)
	// 16-BIT SEGMENT RELATIVE

	// BYTE
public BITS_TABLE	DB	1
	// WORD
		DB	2
	// WORD - BASE
		DB	2
	// PTR
		DB	4
	// HIGH BYTE ;12
		DB	1
	// WIERD WORD
		DB	2
	// PHARLAP FWORD
		DB	6
		DB	1
	// 32-BIT SEGMENT RELATIVE

	// BYTE ?
		DB	1
	// DWORD
		DB	4
	// TLS
		DB	4
	// FWORD
		DB	6
		DB	1
	// WEIRD DWORD
		DB	4
		DB	2 DUP(1)

    version(fg_phar)
    {

PHAR_TO_MS	DB	0,1,2,3,4,9,6,7
		DB	8,9,10,11,12,13,14,15
		DB	16,17,18,19,20,25,27,23
		DB	24,25,26,27,28,29,30,31

    }

		END

